﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace FifthClassAssignment{
    public partial class MainWindow : Form{
        
        private Queue _urls = Queue.Synchronized(new Queue());
        private Dictionary<string,TreeNode> _stored = new Dictionary<string,TreeNode>();

        private string HttpGet(){
            
            var url = (string)_urls.Dequeue();
            var content = "";
            
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
            request.Timeout = 5 * 1000;
            using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
            using (Stream stream = response.GetResponseStream())
            using (StreamReader reader = new StreamReader(stream))
            {
                content = reader.ReadToEnd();
            }
            return content;
        }
        
        private void GetUrl(string content){
            var regex = "href=\"http(.+?)\"";
            var r = new Regex(regex);
            var us = r.Matches(content);
            var e = us.GetEnumerator();
            while (e.MoveNext() && e.Current != null) {
                var match = (Match)e.Current;
                var value = match.Value.Substring(6,match.Value.Length-7);
                _urls.Enqueue(value);
            }
        }

        private Dictionary<string, string> GetNumber(string content,string url){
            var map = new Dictionary<string, string>();
            var regex = "[1][3,4,5,7,8][0-9]{9}";
            var r = new Regex(regex);
            var values = r.Matches(content);
            var e = values.GetEnumerator();
            while (e.MoveNext() && e.Current != null) {
                var match = (Match)e.Current;
                map.Add(match.Value,url);
            }
            return map;
        }


        private void Confirm_Click(object sender,EventArgs e){
            if (!bw.IsBusy) {
                _urls.Enqueue("https://cn.bing.com/search?q="+input.Text);
                bw.RunWorkerAsync(); 
            }
        }

        private void BW_DoWork(object  sender, DoWorkEventArgs e){
            var count = 0;
            while (count < 100) {
                try {
                    var url = (string)_urls.Peek(); 
                    var content = HttpGet();
                    GetUrl(content);
                    var map = GetNumber(content,url);
                    count += map.Count;
                    bw.ReportProgress(count,map);
                }
                catch (Exception ignored) {}
            }
        }

        private void BW_WorkCompleted(object  sender, RunWorkerCompletedEventArgs e){
            numberCount.ForeColor = Color.Green;
            numberCount.Text = "Completed";
        }

        private void BW_ProgressChanged(object sender, ProgressChangedEventArgs e){
            var map = (Dictionary<string, string>)e.UserState;
            foreach (var key in map.Keys) {
                if (_stored.ContainsKey(key)) {
                    _stored[key].Nodes.Add(map[key]);
                }
                else {
                    var node = new TreeNode(key);
                    node.Nodes.Add(map[key]);
                    tree.Nodes.Add(node);
                    _stored.Add(key,node);
                    numberCount.Text = _stored.Count.ToString();
                }
            }
            foreach (var value in map.Values) {
                urls.Items.Add(value);
                urlCount.Text = urls.Items.Count.ToString();
            }
        }
        
        private void AddEvent(){
            confirm.Click += Confirm_Click;
            bw.WorkerReportsProgress = true;
            bw.DoWork += BW_DoWork;
            bw.ProgressChanged += BW_ProgressChanged;
            bw.RunWorkerCompleted += BW_WorkCompleted;
        }

        public MainWindow(){
            InitializeComponent();
            AddEvent();
        }
    }
}